perm filename SAILIB.SAI[SYS,HE] blob
sn#029732 filedate 1973-03-18 generic text, type T, neo UTF8
COMMENT ⊗ VALID 00007 PAGES
RECORD PAGE DESCRIPTION
00001 00001
00003 00002 ENTRY INVERSION,BOUNDED,DECOMPOSE,SOLVE,IMPROVE
00004 00003 INTERNAL SIMPLE PROCEDURE DECOMPOSE(INTEGER NSAFE REAL ARRAY A,LU)
00008 00004 INTERNAL SIMPLE PROCEDURE SOLVE(INTEGER NSAFE REAL ARRAY LU,B,X)
00010 00005 INTERNAL SIMPLE PROCEDURE IMPROVE(INTEGER NSAFE REAL ARRAY A,LU,B,XREFERENCE REAL DIGITS)
00012 00006 INTERNAL SIMPLE PROCEDURE INVERSION(REAL ARRAY RES,MAT)
00013 00007 INTERNAL BOOLEAN SIMPLE PROCEDURE BOUNDED(REAL X,YSAFE REAL ARRAY PINTEGER N)
00016 ENDMK
⊗;
ENTRY INVERSION,BOUNDED,DECOMPOSE,SOLVE,IMPROVE;
BEGIN "SUPPORT"
SAFE INTEGER ARRAY PS[1:50];
SAFE REAL ARRAY R[1:50],DX[1:50];
SIMPLE PROCEDURE SINGULAR(INTEGER WHY);
COMMENT PRINTS ERROR MESSAGES FOR DECOMPOSE AND IMPROVE;
BEGIN
IF (WHY=0) THEN
USERERR(0,1, "MATRIX WITH ZERO ROW IN DECOMPOSE." );
IF (WHY=1) THEN
USERERR(0,1, "SINGULAR MATRIX IN DECOMPOSE. SOLVE WILL DIVIDE BY ZERO." );
IF (WHY=2) THEN
USERERR(0,1, "NO CONVERGENCE IN IMPROVE. MATRIX IS NEARLY SINGULAR." );
END ;
INTERNAL SIMPLE PROCEDURE DECOMPOSE(INTEGER N;SAFE REAL ARRAY A,LU);
COMMENT A,LU[1:N,1:N];
COMMENT USES GLOBAL INTEGER ARRAY PS;
COMMENT COMPUTES TRIANGULAR MATRICES L AND U AND PERMUTATION
MATRIX P SO THAT LU=PA. STORES L-I AND U IN LU.
ARRAY PS CONTAINS PERMUTED ROW INDICES;
COMMENT DECOMPOSE(N,A,A) OVERWRITES A WITH LU;
BEGIN
LABEL ENDKLOOP;
INTEGER I,J,K,PIVOTINDEX;
REAL NORMROW,PIVOT,SIZE,BIGGEST,MULT;
SIMPLE PROCEDURE ILOOP(INTEGER UL;REFERENCE REAL R1,R2);
START_CODE LABEL LP,EU;
MOVE 1,-1('17);
MOVE 2,-2('17);
MOVE 3,-3('17);
SUB 3,K;
JUMPLE 3,EU;
LP: AOJ 1,;
AOJ 2,;
MOVN 4,MULT;
FMPR 4,(1);
FADRM 4,(2);
SOJG 3,LP;
EU: END;
COMMENT INITIALIZE PS,LU AND R;
FOR I←1 STEP 1 UNTIL N DO
BEGIN
PS[I]←I;
NORMROW←0;
FOR J←1 STEP 1 UNTIL N DO
BEGIN
LU[I,J]←A[I,J];
IF (NORMROW<ABS(LU[I,J])) THEN NORMROW←ABS(LU[I,J]);
END;
IF (NORMROW≠0) THEN R[I]←1/NORMROW
ELSE BEGIN R[I]←0; SINGULAR(0); END;
END;
COMMENT GAUSSIAN ELIMINATION WITH PARTIAL PIVOTING;
FOR K←1 STEP 1 UNTIL N-1 DO
BEGIN
BIGGEST←0;
FOR I←K STEP 1 UNTIL N DO
BEGIN
SIZE←ABS(LU[PS[I],K])*R[PS[I]];
IF (BIGGEST<SIZE) THEN
BEGIN BIGGEST←SIZE; PIVOTINDEX←I; END;
END;
IF BIGGEST=0 THEN
BEGIN SINGULAR(1); GO TO ENDKLOOP; END;
IF PIVOTINDEX≠K THEN
BEGIN
J←PS[K];PS[K]←PS[PIVOTINDEX];PS[PIVOTINDEX]←J;
END;
PIVOT←LU[PS[K],K];
FOR I←K+1 STEP 1 UNTIL N DO
BEGIN
LU[PS[I],K]←MULT←(LU[PS[I],K]/PIVOT);
IF MULT ≠0 THEN
COMMENT FOR J←K+1 STEP 1 UNTIL N DO
LU[PS[I],J]←LU[PS[I],J]-MULT*LU[PS[K],J];
ILOOP(N,LU[PS[I],K],LU[PS[K],K]);
COMMENT INNER LOOP. ONLY COLUMN SUBSCRIPT
VARIES. USE MACHINE CODE IF NECESSARY
FOR EFFICIENCY;
END;
ENDKLOOP:
END;
IF (LU[PS[N],N]=0) THEN SINGULAR(1);
END ;
INTERNAL SIMPLE PROCEDURE SOLVE(INTEGER N;SAFE REAL ARRAY LU,B,X);
COMMENT LU[1:N,1:N],B,X[1:N];
COMMENT USES GLOBAL SAFE INTEGER ARRAY PS;
COMMENT SOLVES AX=B USING LU FROM DECOMPOSE;
BEGIN
INTEGER I,J;
REAL DOT;
SIMPLE PROCEDURE ILOOP(INTEGER LL,UL;REFERENCE REAL R1,R2);
START_CODE LABEL LP,EU;
MOVE 1,-1('17);
MOVE 2,-2('17);
MOVE 3,-3('17);
SUB 3,-4('17);
SETZ 4,;
JUMPL 3,EU;
LP: MOVE 5,(1);
FMPR 5,(2);
FADR 4,5;
AOJ 1,;
AOJ 2,;
SOJGE 3,LP;
EU: MOVEM 4,DOT;
END;
FOR I←1 STEP 1 UNTIL N DO
BEGIN
COMMENT DOT←0;
COMMENT FOR J←1 STEP 1 UNTIL I-1 DO
DOT←DOT+LU[PS[I],J]*X[J];
ILOOP(1,I-1,LU[PS[I],1],X[1]);
X[I]←B[PS[I]]-DOT;
END;
FOR I←N STEP -1 UNTIL 1 DO
BEGIN
COMMENT DOT←0;
COMMENT FOR J←I+1 STEP 1 UNTIL N DO
DOT←DOT+LU[PS[I],J]*X[J];
ILOOP(I+1,N,LU[PS[I],I+1],X[I+1]);
X[I]←(X[I]-DOT)/LU[PS[I],I];
END;
COMMENT AS IN DECOMPOSE, THE INNER LOOPS INVOLVE ONLY THE COLUMN
SUBSCRIPT OF LU AND MAY BE MACHINE CODED FOR EFFICIENCY;
END;
INTERNAL SIMPLE PROCEDURE IMPROVE(INTEGER N;SAFE REAL ARRAY A,LU,B,X;REFERENCE REAL DIGITS);
COMMENT A,LU[1:N,1:N],B,X[1:N];
COMMENT A IS THE ORIGINAL MATRIX, LU IS FROM DECOMPOSE,B IS THE
RIGHT HAND SIDE,X IS THE SOLUTION FROM SOLVE. IMPROVES
X TO MACHINE ACCURACY AND SETS DIGITS TO THE NUMBER
OF DIGITS OF X WHICH DO NOT CHANGE;
COMMENT MACHINE DEPENDENT QUANTITIES INDICATED BY 0-0;
BEGIN
LABEL CONVERGED;
INTEGER ITER, ITMAX,I;
REAL RT,T,NORMX,NORMDX,EPS;
EXTERNAL REAL SIMPLE PROCEDURE ADPFOR(INTEGER N;REAL ARRAY A;INTEGER I;REAL ARRAY X;REAL EXTRATERM);
EPS←1.0@-8;
ITMAX←16;
NORMX←0;
FOR I←1 STEP 1 UNTIL N DO
IF (NORMX<ABS(X[I])) THEN NORMX←ABS(X[I]);
IF NORMX=0 THEN GO TO CONVERGED;
FOR ITER ←1 STEP 1 UNTIL ITMAX DO
BEGIN
FOR I←1 STEP 1 UNTIL N DO
R[I]←ADPFOR(N,A,I,X,B[I]);
SOLVE(N,LU,R,DX);
NORMDX←0;
FOR I←1 STEP 1 UNTIL N DO
BEGIN
T←X[I];
X[I]←X[I]+DX[I];
IF (NORMDX<ABS(X[I]-T)) THEN NORMDX←ABS(X[I]-T);
END;
IF (NORMDX≤EPS*NORMX) THEN GO TO CONVERGED;
END ;
COMMENT ITERATION DID NOT CONVERGE;
SINGULAR(2);
CONVERGED:
END;
INTERNAL SIMPLE PROCEDURE INVERSION(REAL ARRAY RES,MAT);
BEGIN "INVERT"
SAFE OWN REAL ARRAY LU[1:4,1:4],B,X[1:4];
INTEGER I,J;
REAL DIGITS;
DECOMPOSE(4,MAT,LU);
FOR J←1 STEP 1 UNTIL 4 DO BEGIN
FOR I← 1 STEP 1 UNTIL 4 DO B[I]←IF I=J THEN 1.0 ELSE 0.0;
SOLVE(4,LU,B,X);
IMPROVE(4,MAT,LU,B,X,DIGITS);
FOR I←1 STEP 1 UNTIL 4 DO RES[I,J]←X[I] END;
END "INVERT";
INTERNAL BOOLEAN SIMPLE PROCEDURE BOUNDED(REAL X,Y;SAFE REAL ARRAY P;INTEGER N);
BEGIN INTEGER I,C,N2,II;
REAL M1,M2,RV,RH;
LABEL NEXTL,ADD4;
C←0;
FOR I←N STEP 2 UNTIL 2*(N-1) DO
BEGIN RV←(P[(I+1) MOD N]-Y)*(Y-P[(I+3) MOD N]);
IF RV<0.0 THEN GO TO NEXTL;
IF RV> 0.0 THEN
BEGIN RH←(P[I MOD N]-X)*(X-P[(I+2) MOD N]);
IF RH < 0.0 THEN
BEGIN C←IF X<P[I MOD N] THEN C+1 ELSE C;
GO TO NEXTL
END;
IF RH>0.0 THEN
BEGIN M1←(P[(I+1) MOD N]-P[(I+3) MOD N])/
(P[I MOD N]-P[(I+2) MOD N]);
M2←(IF P[(I+1) MOD N]>P[(I+3) MOD N] THEN
(P[(I+1) MOD N]-Y)/(P[I MOD N]-X) ELSE
(P[(I+3) MOD N]-Y)/(P[(I+2) MOD N]-X)) ;
IF M1=M2 THEN RETURN (TRUE);
C←IF M1>M2 THEN C+1 ELSE C;
GO TO NEXTL
END;
IF P[I MOD N]=P[(I+2) MOD N] THEN RETURN (TRUE);
IF P[I MOD N]=X THEN
BEGIN C←IF X<P[(I+2) MOD N] THEN C+1 ELSE C
END ELSE C←IF X<P[I MOD N] THEN C+1 ELSE C;
GO TO NEXTL
END;
IF P[(I+1) MOD N]=P[(I+3) MOD N] THEN BEGIN IF (P[I MOD N]-X)*(X-P[(I+2) MOD N])≥0.0
THEN RETURN (TRUE) ELSE GO TO NEXTL END;
II← IF Y=P[(I+1) MOD N] THEN I ELSE I+2;
IF X>P[II MOD N] THEN GO TO ADD4;
IF X<P[II MOD N] THEN
BEGIN C←IF (P[(II+3) MOD N]-P[(II+1) MOD N])*
(P[(II+1) MOD N]-P[(II-1) MOD N])>0.0 THEN C+1 ELSE C;
GO TO ADD4
END;
RETURN (TRUE);
ADD4: I←I+2;
NEXTL: END;
RETURN(IF C MOD 2 =1 THEN TRUE ELSE FALSE)
END;
END "SUPPORT"